from django.views.generic import View
from libs import json_response, JsonParser, Argument
from apps.application.models import Register, Application
from apps.account.models import Role
from libs import human_datetime, AttrDict
from libs.eureka_client import Eureka

import random

APPLICATION_STATUS = (
    'UP',
    'OUT_OF_SERVICE'
)

class RegisterView(View):
    def get(self, request):
        register_id = request.GET.get('id')
        if register_id:
            return json_response(Register.objects.get(pk=register_id))
        registers = Register.objects.filter(deleted_by_id__isnull=True)

        return json_response(registers)

    def post(self, request):
        form, error = JsonParser(
            Argument('id', type=int, required=False),
            Argument('url', help='请输入注册中心链接'),
            Argument('name', help='请输入注册中心名称'),
            Argument('type', handler=str.strip, help='请选择注册中心类型'),
            Argument('desc', required=False),
        ).parse(request.body)

        if error is None:
            if form.id:
                # 如果传的参数带id,则更新IDC
                Register.objects.filter(pk=form.pop('id')).update(**form)
            elif Register.objects.filter(name=form.name, deleted_by_id__isnull=True).exists():
                # register名称唯一，如果已存在相同的register名称则报错
                return json_response(error=f'已存在的注册中心名称【{form.name}】')
            else:
                # 新建Register记录
                register = Register.objects.create(created_by=request.user, **form)
                if request.user.role:
                    request.user.role.add_host_perm(register.id)
        return json_response(error=error)

    def delete(self, request):
        form, error = JsonParser(
            Argument('id', type=int, help='请指定操作对象')
        ).parse(request.GET)
        if error is None:
            role = Role.objects.filter(host_perms__regex=fr'[^0-9]{form.id}[^0-9]').first()
            application = Application.objects.filter(register_id=form.id, deleted_by_id__isnull=True).first()
            if role:
                return json_response(error=f'角色【{role.name}】的主机权限关联了该主机，请解除关联后再尝试删除该主机')
            if application:
                return json_response(error=f'APP【{application.name}】关联了该注册中心，请解除关联后再尝试删除该注册中心')
            Register.objects.filter(pk=form.id).update(
                deleted_at=human_datetime(),
                deleted_by=request.user,
            )
        return json_response(error=error)


class ApplicationView(View):
    def get(self, request):
        application_id = request.GET.get('id')
        if application_id:
            return json_response(Application.objects.get(pk=application_id))
        applications = Application.objects.filter(deleted_by_id__isnull=True)
        perms = [x.id for x in applications]
        registers = Register.objects.filter(deleted_by_id__isnull=True)
        return json_response({'apps': [x.to_dict() for x in applications], 'perms': perms, 'registers': [x.to_dict() for x in registers]})

    def post(self, request):
        form, error = JsonParser(
            Argument('id', type=int, required=False),
            Argument('register_id', help='请选择注册中心'),
            Argument('socket', help='APP地址'),
            Argument('name', help='请输入APP名称'),
            Argument('desc', required=False),
        ).parse(request.body)

        if error is None:
            if form.id:
                pass
            elif Application.objects.filter(name=form.name, register_id=form.register_id, socket=form.socket, deleted_by_id__isnull=True).exists():
                return json_response(error=f'已存在的APP【{form.name}】')
            else:
                # 创建
                register = Register.objects.filter(pk=form.register_id).first()
                application = Application.objects.create(created_by=request.user, **form)
                if request.user.role:
                    request.user.role.add_host_perm(application.id)
        return json_response(error=error)

    def delete(self, request):
        form, error = JsonParser(
            Argument('id', type=int, help='请指定操作对象')
        ).parse(request.GET)
        if error is None:
            role = Role.objects.filter(host_perms__regex=fr'[^0-9]{form.id}[^0-9]').first()
            if role:
                return json_response(error=f'角色【{role.name}】的主机权限关联了该用户，请解除关联后再尝试删除该VPN用户')

            vpnuser_queryset = VpnUser.objects.filter(pk=form.id)
            vpnuser_queryset.update(deleted_at=human_datetime(), deleted_by=request.user,)
            vpnuser = vpnuser_queryset.first()
            vpnserver = VpnServer.objects.filter(pk=vpnuser.vpnserver_id).first()
            if vpnserver.type in ('huaweicloud', 'fastapi'):
                return json_response(error=f"此类型VPN服务暂不支持在线删除用户。")
            client = get_vpn_client(vpnserver)
            res = client.userdel(vpnuser.name)

        return json_response(error=error)

    def options(self, request):
        form, error = JsonParser(
            Argument('id', type=int, help='请指定操作对象'),
            Argument('status', type=int, help='请指定操作对象')
        ).parse(request.GET)
        if error is None:
            application = Application.objects.filter(pk=form.id).first()
            application.status = APPLICATION_STATUS[form.status]
            register = Register.objects.filter(pk=application.register_id).first()
            client = get_register_client(register)
            if client:
                ipaddress, port = application.socket.split(':')
                app = client.get_app(ipaddress, port)
                client.change_app_status(app, form.status)
                application.save()

        return json_response(error=error)


def get_register_client(register):
    if register.type == 'eureka':
        client = Eureka('{}eureka/apps/'.format(register.url))
    else:
        return False
    return client


def sync_import(request):
    summary = {'create': [], 'update': [], 'invalid': [], 'skip': [], 'fail': [], 'network': [], 'repeat': [], 'success': [], 'error': []}
    register_id = request.POST.get('register_id')
    register = Register.objects.filter(pk=register_id).first()
    if not register.url or not register.type:
        return json_response(error=f'注册中心关键信息缺失，无法同步。')
    if register.type == 'eureka':
        client = Eureka('{}eureka/apps/'.format(register.url))
        apps = client.get_registry_apps()
        for app in apps:
            app.pop('instanceid')
            app.pop('hostname')
            app['register_id'] = register_id

            if Application.objects.filter(name=app['name'], socket=app['socket']):
                # update
                Application.objects.filter(name=app['name'], socket=app['socket']).update(**app)
            else:
                Application.objects.create(created_by=request.user, **app)
    else:
        return json_response(error=f'暂不支持的注册中心类型')

    return json_response(summary)
